package middleware

import (
	"context"
	"errors"
	"github.com/RaymondCode/simple-demo/config"
	"github.com/RaymondCode/simple-demo/entity/myerr"
	"github.com/RaymondCode/simple-demo/entity/response"
	"github.com/RaymondCode/simple-demo/util/jwtutil"
	"github.com/RaymondCode/simple-demo/util/redisutil"
	"github.com/cloudwego/hertz/pkg/app"
	"log"
	"net/http"
	"strconv"
	"strings"
)

func JWTAuth(c context.Context, ctx *app.RequestContext) {
	var err error
	var tokenString string
	path := string(ctx.Request.Path())
	isFeed := strings.Contains(path, "/feed")
	isPublish := strings.Contains(path, "/publish/action")
	if isPublish {
		// 投稿接口 通过form-data获取token
		tokenString = ctx.PostForm("token")
	} else if isFeed {
		// feed流接口，只用获取token，且没有token不拦截
		tokenString = ctx.Query("token")
		if tokenString == "" {
			ctx.Next(c)
			return
		}
	} else {
		tokenString = ctx.Query("token")
	}
	// 解析token
	err, uid := parseToken(ctx, tokenString)
	if err != nil {
		log.Println(err)
		return
	}
	if !isFeed {
		err = tokenValid(ctx, uid)
		if err != nil {
			log.Println(err)
			return
		}
	}
	// 存入uid，供线程变量中间件操作
	ctx.Set(config.Config.ThreadLocal.Keys.UserId, uid)
	ctx.Next(c)
}

func parseToken(ctx *app.RequestContext, token string) (error, int) {
	uid, err := jwtutil.ParseJWT(token)
	if err != nil {
		// token过期
		ctx.JSON(http.StatusBadRequest, response.ErrorResponse(myerr.InvalidToken))
		ctx.Abort()
	}
	return err, uid
}

func tokenValid(ctx *app.RequestContext, userId int) error {
	var redisToken string
	err := redisutil.Get[string](config.Config.Redis.Key.Token+strconv.Itoa(userId), &redisToken)
	if err != nil || redisToken == "" {
		ctx.JSON(http.StatusBadRequest, response.ErrorResponse(myerr.InvalidToken))
		ctx.Abort()
		return errors.New("redis中token不存在")
	}
	return err
}
